import redis
from django.core.cache import cache
from django.apps import apps
from django.db import connection, DatabaseError, OperationalError, close_old_connections
from functools import wraps
import logging

logger = logging.getLogger(__name__)


def ensure_db_connection(func):
    """
    装饰器：确保数据库连接有效
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            connection.cursor().execute("SELECT 1")
        except Exception as e:
            logger.error(f"数据库连接无效，错误信息: {e}，尝试重新连接...")
            try:
                connection.close()
                close_old_connections()
                connection.connect()
                logger.info("数据库连接已重新建立")
            except Exception as reconnection_error:
                logger.error(f"重新连接数据库失败，错误信息: {reconnection_error}")
        return func(*args, **kwargs)

    return wrapper


@ensure_db_connection
def load_tolerance_table():
    """
    加载公差表并缓存到 Redis
    """
    # 动态获取模型
    try:
        # 动态获取模型
        EphmLimits = apps.get_model("ephm_api", "EphmLimits")
        tolerances = EphmLimits.objects.all()
        tolerance_table = {(t.zone, t.op, t.item): (t.low_limit, t.up_limit, t.item_cn, t.item_level) for t in tolerances}
        cache.set("tolerance_table", tolerance_table)
        return tolerance_table
    except (DatabaseError, OperationalError) as e:
        print(f"数据库操作出错: {e}")
        return None
    except Exception as e:
        print(f"发生未知错误: {e}")
        return None


def get_tolerance(zone, op, item):
    """
    从缓存中获取某个资产的公差范围
    :param zone: 区域
    :param op: 操作
    :param item: 项目
    :return: 公差范围 (low_limit, up_limit)
    """
    tolerance_table = cache.get("tolerance_table")
    if not tolerance_table:
        tolerance_table = load_tolerance_table()
    return tolerance_table.get((zone, op, item), (None, None, None, None))


def get_cache_key(zone, op, item):
    """
    生成缓存键
    :param zone: 区域
    :param op: 工位
    :param item: 测点
    :return: 缓存键
    """
    return f"overlimit:{zone}:{op}:{item}"


def clear_tolerance_cache():
    """
    清空公差表缓存
    """
    cache.delete("tolerance_table")


def update_tolerance_cache(zone=None, op=None, item=None):
    """
    更新指定区域/工位/测点公差表缓存
    :param zone: 指定区域，如果为 None 则更新全部数据
    :param op: 指定操作，如果为 None 则更新全部数据
    :param item: 指定项目，如果为 None 则更新全部数据
    :return: True 表示成功，False 表示失败
    """
    # 动态获取模型
    EphmLimits = apps.get_model("ephm_api", "EphmLimits")
    # 如果没有指定条件，重新加载整个公差表
    if not zone and not op and not item:
        load_tolerance_table()
        return True

    # 构建过滤条件
    filter_kwargs = {}
    if zone:
        filter_kwargs["zone"] = zone
    if op:
        filter_kwargs["op"] = op
    if item:
        filter_kwargs["item"] = item

    # 根据过滤条件查询数据
    tolerances = EphmLimits.objects.filter(**filter_kwargs)
    if not tolerances.exists():
        return False  # 没有找到符合条件的记录

    # 更新缓存中的部分数据
    tolerance_table = cache.get("tolerance_table", {})
    for tolerance in tolerances:
        tolerance_table[(tolerance.zone, tolerance.op, tolerance.item)] = (tolerance.low_limit, tolerance.up_limit, tolerance.item_cn, tolerance.item_level)
    cache.set("tolerance_table", tolerance_table)
    return True


def get_cache_data(redis_client, key):
    """
    从 Redis 中获取缓存数据
    :param redis_client: Redis 客户端
    :param key: 缓存键
    :return: 缓存数据，如果不存在则返回 None
    """
    try:
        data = redis_client.get(key)
        if data:
            return data.decode("utf-8")
        return None
    except Exception as e:
        print(f"从Redis中获取缓存数据出错: {e}")
        return None


def set_cache_data(redis_client, key, value):
    """
    向 Redis 中设置缓存数据
    :param redis_client: Redis 客户端
    :param key: 缓存键
    :param value: 缓存值
    """
    try:
        if value is None:
            redis_client.delete(key)
        else:
            redis_client.set(key, value)
    except Exception as e:
        print(f"向Redis中设置缓存数据出错: {e}")
